//  IDVI 1.0 source copyright 1996 Garth A. Dickie
//
//  This source is free for non-commercial use.  No warranty, etc.
//  Please acknowledge reuse by including the line:
//
//  "Based in part on IDVI 1.0 source copyright 1996 Garth A. Dickie"
//
//  in your documentation and source code.  For commercial use or
//  distribution, please contact the author.  Please also send
//  questions, comments, bug reports, or fixes.
//
//  Best Regards,
//  Garth A. Dickie
//  dickie@elastic.avid.com

package ibook.v10.idvi.controls;

import java.awt.Canvas;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;

import ibook.v10.idvi.IDVI;

final class MessageCanvas extends Canvas implements Runnable {
    private String  defaultMessage;
    private String  message;
    private Thread  thread;

    MessageCanvas( String defaultMessage ) {
        this.defaultMessage = defaultMessage;
        this.message = defaultMessage;

        thread = new Thread( this );
        thread.start( );
    }

    public void showMessage( String message ) {
        setMessage( message );
        repaint( );
    }

    public Dimension preferredSize( ) {
        return minimumSize( );
    }

    public Dimension minimumSize( ) {
        FontMetrics metrics = getFontMetrics( getFont( ));

        int xOffset = metrics.charWidth( ' ' );
        int yOffset = metrics.getLeading( ) + metrics.getAscent( );
        int width = 2 * xOffset + metrics.stringWidth( defaultMessage );
        int height = yOffset + metrics.getDescent( ) + metrics.getLeading( );

        return new Dimension( width, height );
    }

    public void paint( Graphics g ) {
        FontMetrics metrics = getFontMetrics( getFont( ));

        int xOffset = metrics.charWidth( ' ' );
        int yOffset = metrics.getLeading( ) + metrics.getAscent( );

        g.drawString( message, xOffset, yOffset );
    }

    // ??? When does this thread get killed?

    final private static long   kFudgeFactorMillis = 50;
    private long                resetTime;
    private boolean             needsReset = false;

    private synchronized void setMessage( String message ) {
        this.message = message;
        needsReset = true;
        resetTime = System.currentTimeMillis( ) + IDVI.kControlsMessageDelay;
        notify( );
    }

    private synchronized void waitForNeedsReset( ) {
        while( ! needsReset )
            try {
                wait( );
            } catch( InterruptedException e ) {
            }
    }

    private synchronized long clearMessageOrGetSleepTime( ) {
        long sleepTime = resetTime - System.currentTimeMillis( );

        if( sleepTime <= kFudgeFactorMillis ) {
            message = defaultMessage;
            needsReset = false;
            sleepTime = 0;
        }

        return sleepTime;
    }

    public void run( ) {
        thread.setPriority( Thread.MIN_PRIORITY );

        while( true ) {
            waitForNeedsReset( );

            long sleepTime = clearMessageOrGetSleepTime( );
            while( sleepTime > kFudgeFactorMillis ) {
                try {
                    thread.sleep( sleepTime );
                } catch( InterruptedException e ) {
                }

                sleepTime = clearMessageOrGetSleepTime( );
            }
            repaint( );
        }
    }
}
